// 当前项目包的入口文件

// 封装一个render()函数
// 将render函数挂载到res对象上，可以通过res.render()来访问
// 实现post方式提交新闻


// 1.引入http模块
const http = require('http');
const fs = require("fs"); //文件模块
const path = require("path");//路径模块
const url = require("url");//url模块
const querystring = require('querystring'); // 将post提交数据的查询字符串转换为json对象

// 外部模块
// mime 模块
const mime = require('mime');
const _ = require("underscore");


http.createServer(function(req,res){
	// 路由由2中形式组成 请求方式+请求方法
	
	// 将render挂载到res对象上，可以通过res.render()来访问
	res.render=function(filename,tplData){
		fs.readFile(filename,(err,data)=>{
		if(err){
			return res.end('404 Not Found!');		
		}else{
			// 如果用户传递了模板数据，那么就使用underscore的template方法进行替换
			// 如果用户没有传递模板数据，那么就不进行替换
			if(tplData){
				// 如果用户传递了模板数据，则进行模板替换
				var fn = _.template(data.toString('utf8')); // 模板字符串
				data = fn(tplData); // 将数据替换模板字符串
			}
			res.setHeader('Content-type',mime.getType(filename));
			console.log(fn);
			res.end(data);
		}
	  });
	}
	
	req.url = req.url.toLowerCase();
	req.method = req.method.toLowerCase();
	
    // 通过url模块,调用url.parse()方法解析用户请求的url(req.url);
	var urlobj = url.parse(req.url,true); // 加了true后，可以把get提交的数据解析为对象，我们可以通过query.title去获取相应的数据
	
	if(req.url.startsWith('/resource')){
		// 这里请求的是静态资源，静态资源直接用请求的路径拼接好
		res.render(path.join(__dirname,req.url));
	}else if(urlobj.pathname==='/item' && req.method==='get'){
		// 1 获取当前的新闻id
		   console.log(urlobj.query.id);
		   
		   
		// 2 获取data.json中的数据，根据id，找到对应的新闻
			fs.readFile(path.join(__dirname,'data.json'),(err,data)=>{
			if(err && err!=="ENOENT"){
				throw err;
			}else{
				var list = JSON.parse( data || '[]');
				// 循环list中的数据，找到和id值相等的数据
				var mode = null;
				for(var i=0;i<list.length;i++){
					if(list[i].id===parseInt(urlobj.query.id)){
						mode = list[i];
						break;
					}
				}
				
				if(mode){
					res.render(path.join(__dirname,'views','details.html'),{list:mode});
				}else{
					res.end('No Such Item');
				}
			}
			
		})
		
		// 3调用res.render函数进行模板引擎的渲染
		
	}	
	else if((req.url==='/' || req.url==="/index") && req.method==='get'){
		
		fs.readFile(path.join(__dirname,'data.json'),(err,data)=>{
			if(err && err!=="ENOENT"){
				throw err;
			}else{
				var list = JSON.parse( data || '[]');
				res.render(path.join(__dirname,'views','index.html'),{datalist:list});
			}
		})
		
		
		
	}
	else if(req.url.startsWith('/add') && req.method==='get'){
		// 要获取用户get提交的数据,需要用到url模块(这个模块是node内置的模块)
		// 既然是get提交数据，所以通过req.url
		
		// 1 获取用户get提交过来的新闻数据
		// urlobj.query.title
		// urlobj.query.url
		// urlobj.query.content
		
		// 2 将用户提交的数据保存到data.json文件中，为了每次提交的数据不覆盖之前的数据，我们每次先去读取data.json中 的数据取出，放到数组中去，然后再把本次提交的数据push到数据去，这样就不会覆盖。		
		fs.readFile(path.join(__dirname,'data.json'),'utf8',(err,data)=>{
//			因为第一次访问网站,data.json文件本身不存在,所以肯定是 有错误的,但是这种错误,我们并不认为是网站出错了,所以不需要抛出异常.
			if(err && err!=="ENOENT"){
				throw err;
			}			
			var list = JSON.parse(data || '[]'); //防止没有数据报错，因为json.parse转换null 或者 undefined会报错。	
			
			// 给新闻增加一个id属性
			urlobj.query.id = list.length;
			list.push(urlobj.query);
		// 把list数组中的数据写入到data.json中
		fs.writeFile(path.join(__dirname,'data.json'),JSON.stringify(list),(err)=>{
			if(err){
				throw err;
			}
			
			// 设置响应报文头，通过响应报文头告诉浏览器，执行一次页面跳转操作
			
			// 3 跳转到新闻列表页
			
			// 重定向
			res.statusCode = 302;
			res.statusMessage='Found';
			res.setHeader("Location",'index.html');
			res.end();//每一个请求都要结束响应
		});	
		})		
	}else if(req.url==='/add' && req.method ==='post'){
		// 1 读取data.json文件中的数据
		fs.readFile(path.join(__dirname,'data.json'),'utf8',(err,data)=>{
//			因为第一次访问网站,data.json文件本身不存在,所以肯定是 有错误的,但是这种错误,我们并不认为是网站出错了,所以不需要抛出异常.
			if(err && err!=="ENOENT"){
				throw err;
			}		
			// 2 将读取到的数据转换为list数组
			var list = JSON.parse(data || '[]'); //防止没有数据报错，因为json.parse转换null 或者 undefined会报错。		
			// 如何获取用户post提交的数据
			// 因为post提交数据的时候，数据量可能比较大，所以会分多次进行比较，每次提交一部分数据， 此时想要在服务器中获取用户提交的数据，就必须监听 request事件的data事件(因为每次浏览器提交一部分数据到服务器)
			// 那么，什么时候才表示浏览器把所有数据都提交到服务器了呢？就是当request的end事件被触发的时候。
			
			// 监听request 的对象的data事件 和 end 事件代码如下：
			// 声明一个数组，用来保存用户每次提交过来的数据
			var arr =[];
			req.on('data',function(chunk){
				// 此处的chunk参数，就是浏览器本次提交过来的一部分数据
				// chunk的数据类型是Buffer
				arr.push(chunk);
			})
			
				// 监听request对象的end事件
				// 当end事件被触发的时候，表示所有数据都已经提交完毕了				
			req.on('end',function(){
				// 在这个事件中只要把arr中的所有数据都汇总起来就好了
				// 把arr中的每个buffer对象 集合起来转换为一个buffer对象
				var postBody = Buffer.concat(arr);
				// 把获取到buffter对象转换为一个字符串
				postBody = postBody.toString('utf-8');
				
				// 把post 请求的查询字符串，转换为一个json对象.node中post请求通过querystring.parse()来将我们提交过来的查询字符串 title=111&url=fff转换为json对象
				postBody = querystring.parse(postBody);
				
				postBody.id = list.length;
				//将用户提交到新闻push到list中
				list.push(postBody);
				
				// 将新的数据写入到data.json中
					// 把list数组中的数据写入到data.json中
		fs.writeFile(path.join(__dirname,'data.json'),JSON.stringify(list),(err)=>{
			if(err){
				throw err;
			}
			
			// 设置响应报文头，通过响应报文头告诉浏览器，执行一次页面跳转操作
			
			// 3 跳转到新闻列表页
			
			// 重定向
			res.statusCode = 302;
			res.statusMessage='Found';
			res.setHeader("Location",'index.html');
			res.end();//每一个请求都要结束响应
		});	
			});
			
			});
		
		
		// 3 向list 数组中push本次提交的新闻 
		
		// 4 把list数组重新转换为字符串写到data.json中
		
		// 5 重定向
	}
	else{
		//		把所有要访问的页面都统一放在一个文件夹下面
		var viewsDir = path.join(__dirname,'views');
		var filename = path.join(viewsDir,req.url);
		res.render(filename);	
	}
	
}).listen(7070,function(){
	console.log("http://localhost:7070")
})


//封装一个render函数
//function render(filename,res){
//	fs.readFile(filename,(err,data)=>{
//		if(err){
//			return res.end('404 Not Found!');		
//		}else{
//			res.setHeader('Content-type',mime.getType(filename));
//			res.end(data);
//		}
//	})	
//}
